<?php
/**
 *+------------------
 * Lflow
 *+------------------
 * Copyright (c) 2023~2030 gitee.com/liu_guan_qing All rights reserved.本版权不可删除，侵权必究
 *+------------------
 * Author: Mr.April(405784684@qq.com)
 *+------------------
 */
declare (strict_types=1);

namespace lflow\ckpt;

use lflow\core\Execution;
use lflow\exceptions\WorkFlowException;
use lflow\impl\JuelExpression;
use lflow\lib\interface\DecisionHandler;
use lflow\lib\interface\Expression;
use lflow\lib\util\ClassUtil;
use lflow\lib\util\Logger;
use lflow\lib\util\StringHelper;

/**
 * 决策定义Decision元素
 *
 * @author Mr.April
 * @since  1.0
 */
class DecisionCkpt extends NodeCkpt
{

    /**
     * 决策选择表达式串（需要表达式引擎解析）
     */
    private string|null $expr;

    /**
     * 决策处理类，对于复杂的分支条件，可通过handleClass来处理
     */
    private string $handleClass;

    /**
     * 决策处理类实例
     */
    private DecisionHandler $decide;

    /**
     * 表达式解析器
     */
    private Expression $expression;

    /**
     * @param \lflow\core\Execution $execution
     */
    public function exec(Execution $execution): void
    {
        $args = $execution->getOrder()->getData('variable');
        Logger::info($execution->getOrder()->getData('id') . "->decision execution.getArgs():" . json_encode($execution->getArgs()));
        $Expression = new JuelExpression();
        Logger::info("expression is " . json_encode($Expression));
        //决策表达式
        if (StringHelper::isNotEmpty($this->expr)) {
            $next = null;
        } else {
            $next = null;
        }
        $isFound = false;
        Logger:: info($execution->getOrder()->getData('id') . "->decision expression[expr=" . $this->expr . "] return result:" . $next);
        foreach ($this->getOutputs() as $tm) {
            if (StringHelper::isEmpty($next)) {
                //无决策点expr 使用变迁
                $expr = $tm->getExpr();
                Logger::error('决策表达式参数'.json_encode($tm));
                if (StringHelper::isNotEmpty($expr) && $Expression->eval($expr, $args)) {
                    $tm->setEnabled(true);
                    $tm->execute($execution);
                    $isFound = true;
                }
            } else {
                if (StringHelper::equalsIgnoreCase($tm->getName(), $next)) {
                    $tm->setEnabled(true);
                    $tm->execute($execution);
                    $isFound = true;
                }
            }
        }
        if (!$isFound) throw new WorkFlowException($execution->getOrder()->getData('id') . "->decision节点无法确定下一步执行路线");
    }

    public function getExpr(): string
    {
        return $this->expr;
    }

    public function setExpr(string|null $expr): void
    {
        $this->expr = $expr;
    }

    public function getHandleClass(): string
    {
        return $this->handleClass;
    }

    public function setHandleClass(string|null $handleClass): void
    {
        $classZ            = str_replace('/', '\\', !empty($handleClass) ? $handleClass : '');
        $this->handleClass = $classZ;
        if (StringHelper::isNotEmpty($classZ)) {
            $this->decide = ClassUtil::instantiateClass($classZ);
        }
    }

}
